// Copyright (c) 2005  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of cgal-python; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with cgal-python.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Id: Py_Point_3.cpp 167 2007-11-02 15:36:54Z spion $
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal-python/trunk/cgal-python/bindings/Kernel/Py_Point_3.cpp $
//
// Author(s)     : Naceur Meskini
//=========================================================================

#include <CGAL/basic.h>
#include <include/Kernels.h>

#include <boost/python.hpp>
#include <boost/cstdint.hpp>

const char* Point_3_doc[] =
{
"An object of the class Point_3 is a point in the three-dimensional Euclidean space\n",
"p = Point_3(ORIGIN)\n\
introduces a point with Cartesian coordinates(0,0,0).\n\n\
p = Point_3(hx,hy,hz,hw = 1)\n\
introduces a point p initialized to (hx/hw,hy/hw, hz/hw).\n\
Precondition: hw #0. ",
"x(self) -> returns the Cartesian  x coordinate, that is hx/hw.\n",

"y(self) -> returns the Cartesian  y coordinate, that is hy/hw.\n",

"z(self) -> returns the Cartesian  z coordinate, that is hz/hw.\n",

"hx(self) -> returns the homogeneous x coordinate.\n",

"hy(self) -> returns the homogeneous y coordinate.\n",

"hz(self) -> returns the homogeneous z coordinate.\n",

"hw(self) -> returns the homogenizing coordinate.\n",

"dimension(self) -> returns the dimension (the constant 3).\n",

"homogeneous(self,i) -> returns the i'th homogeneous coordinate of p, starting with 0.Precondition: 0 <= i <= 2.\n",

"bbox(self) -> returns a bounding box containing p.\n"\
"Note that bounding boxes are not parameterized with whatsoever.\n",

"p[i] -> returns cartesian(i).Precondition: 0 <= i <= 2.\n",

"cartesian(self,i) -> returns the i'th Cartesian  coordinate of p, starting with 0.\nPrecondition: 0 <= i <= 2.\n",

"transform(self,Aff_transformation_2<Kernel> t) -> returns the point obtained by applying t on p.\n"
};

template<class Point_3>
boost::python::str py_repr_Point_3(const Point_3& pt )
{
	using namespace boost::python;
	return str("Point_3("+ str(pt.x()) +","+ str(pt.y())+","+ str(pt.z()) +")" );
}

template <class kernel > 
void Py_Point_3()
{
	using namespace boost::python;

	typedef typename kernel::Point_3 							Point_3;
 	typedef typename kernel::Vector_3 							Vector_3;
 	typedef typename kernel::FT 								FT;

        class_< Point_3 >("Point_3", Point_3_doc[0], init<>())
        .def(init< const Point_3& >(Point_3_doc[1]))
        .def(init< const CGAL::Origin& >())
        .def(init< const FT&, const FT&, const FT& >())
        .def(init< const FT&, const FT&, const FT&, const FT& >())
        .def(init< const double&, const double&, const double& >())
        .def(init< const double&, const double&, const double&, const double& >())
	.def("__repr__", &py_repr_Point_3<Point_3>)

#if CGAL_VERSION_NR < 1030301000 // 3.3.0
        .def("x", &Point_3::x, by_cref(), Point_3_doc[2])
        .def("y", &Point_3::y, by_cref(), Point_3_doc[3])
        .def("z", &Point_3::z, by_cref(), Point_3_doc[4])
        .def("hx", &Point_3::hx, by_cref(), Point_3_doc[5])
        .def("hy", &Point_3::hy, by_cref(), Point_3_doc[6])
        .def("hz", &Point_3::hz, by_cref(), Point_3_doc[7])
        .def("hw", &Point_3::hw, Point_3_doc[8])
#else
        .def("x", &Point_3::x, typename Value_or_cref<typename kernel::Compute_x_3, Point_3 > ::type(), Point_3_doc[2])
        .def("y", &Point_3::y, typename Value_or_cref<typename kernel::Compute_y_3, Point_3 > ::type(), Point_3_doc[3])
        .def("z", &Point_3::z, typename Value_or_cref<typename kernel::Compute_z_3, Point_3 > ::type(), Point_3_doc[4])
        .def("hx", &Point_3::hx, typename Value_or_cref<typename kernel::Compute_hx_3, Point_3 > ::type(), Point_3_doc[5])
        .def("hy", &Point_3::hy, typename Value_or_cref<typename kernel::Compute_hy_3, Point_3 > ::type(), Point_3_doc[6])
        .def("hz", &Point_3::hz, typename Value_or_cref<typename kernel::Compute_hz_3, Point_3 > ::type(), Point_3_doc[7])
        .def("hw", &Point_3::hw, typename Value_or_cref<typename kernel::Compute_hw_3, Point_3 > ::type(), Point_3_doc[8])
#endif
        .def("dimension", &Point_3::dimension, Point_3_doc[9])
        .def("homogeneous", &Point_3::homogeneous, Point_3_doc[10])
        .def("bbox", &Point_3::bbox, Point_3_doc[11])
#if CGAL_VERSION_NR < 1030301000 // 3.3.0
	.def("__getitem__", &Point_3::operator[], by_cref(), Point_3_doc[12])
        .def("cartesian", &Point_3::cartesian, by_cref(), Point_3_doc[13])
#else
	.def("__getitem__", &Point_3::operator[], typename Value_or_cref<typename kernel::Compute_x_3, Point_3 > ::type(), Point_3_doc[12])
        .def("cartesian", &Point_3::cartesian, typename Value_or_cref<typename kernel::Compute_x_3, Point_3 > ::type(), Point_3_doc[13])
#endif
        .def("transform", &Point_3::transform, Point_3_doc[14])
	.def(self == self)
	.def(self != self)
	.def(self < self)
	.def(self > self)
	.def(self <= self)
	.def(self >= self)
	.def(self + Vector_3())
	.def(self - self)
	.def(self - Vector_3())
	.def(self - CGAL::Origin())
    ;
}


void export_Point_3()
{
	Py_Point_3<K>();
}
